package otcv.hr.log;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.Calendar;
import java.util.Locale;

import otcv.hr.conf.Config;
import otcv.hr.util.DateUtil;
import otcv.hr.util.FileHelper;

/**
 * @author : H-Thien
 * @comment : Log Writer
 */
public class LogWriter {

	private static LogWriter instance = new LogWriter();
	private int logLevel = 0;
	private String logFormat = "day";

	public static final int ERROR_LOG = 1;
	public static final int WARNING_LOG = 2;
	public static final int INFO_LOG = 3;
	public static final int DEBUG_LOG = 4;

	public static final int ERROR_LOG_LABEL = 'E';
	public static final int WARNING_LOG_LABEL = 'W';
	public static final int INFO_LOG_LABEL = 'I';
	public static final int DEBUG_LOG_LABEL = 'D';

	private static PrintWriter writer = null;
	private static String logFilePath = null;

	/**
	 * @comment :
	 */
	public static LogWriter getInstance() {
		return instance;
	}

	/**
	 * @comment :
	 */
	private LogWriter() {
		String logLevel = Config.getInstance().getString("log.level", "4");
		this.logLevel = Integer.parseInt(logLevel);
		logFormat = Config.getInstance().getString("log.format", "day");
	}

	/**
	 * @comment :
	 */
	public void write(int logLevel, String message) {
		if (this.logLevel >= logLevel) {
			String logDir = Config.getInstance().getString("log.dir");
			try {
				Calendar calendar = Calendar.getInstance(Locale.getDefault());
				StringBuffer datetimemin = new StringBuffer();
				String s0 = Integer.toString(calendar.get(Calendar.YEAR));
				String s = Integer.toString(calendar.get(Calendar.MONTH) + 1);
				s = s.length() == 1 ? "0" + s : s;
				String s1 = Integer.toString(calendar.get(Calendar.DATE));
				s1 = s1.length() == 1 ? "0" + s1 : s1;
				String s2 = Integer.toString(calendar.get(Calendar.HOUR_OF_DAY));
				s2 = s2.length() == 1 ? "0" + s2 : s2;

				if (logFormat.equals("day")) {
					datetimemin.append(s0); // year
					datetimemin.append(s); // month
					datetimemin.append(s1); // day
				} else {
					datetimemin.append(s0); // year
					datetimemin.append(s); // month
					datetimemin.append(s1); // day
					datetimemin.append(s2); // hour
				}

				StringBuffer date = new StringBuffer(8 + 1);
				date.append(s0);
				date.append(s);
				date.append(s1);

				try {
					if (FileHelper.exist(logDir + "/" + date.toString()) == false) {
						FileHelper.createDirectory(logDir, date.toString());
					}
				} catch (Exception e) {
					e.printStackTrace();
				}

				String pjName = Config.getInstance().getString("project.name", "mflare");
				pjName = pjName + "_";
				if (writer == null || logFilePath == null) {
					logFilePath = logDir + File.separator + date.toString() + File.separator + pjName + datetimemin.toString() + "_service.log";
					FileOutputStream outputStream = new FileOutputStream(logFilePath, true);
					writer = new PrintWriter(new OutputStreamWriter(outputStream, "UTF-8"));
				} else {
					String newFilePath = logDir + File.separator + date.toString() + File.separator + pjName + datetimemin.toString() + "_service.log";
					if (newFilePath.equals(logFilePath) == false) {
						synchronized (writer) {
							writer.close();
							logFilePath = newFilePath;
							FileOutputStream outputStream = new FileOutputStream(logFilePath, true);
							writer = new PrintWriter(new OutputStreamWriter(outputStream, "UTF-8"));
						}
					}
				}

				Exception e = new Exception();
				StackTraceElement element = e.getStackTrace()[3];
				String clazz = element.getClassName().substring(element.getClassName().lastIndexOf(".") + 1);
				String method = element.getMethodName();

				StringBuffer buffer = new StringBuffer();
				buffer.append(getLogLevelChar(logLevel)).append(",");
				buffer.append(DateUtil.getCurrentDateInfo("7")).append(",");
				buffer.append("service").append(",");
				buffer.append(clazz).append(",");
				buffer.append(method).append(",");
				buffer.append(message);
				writer.println(buffer.toString());
				writer.flush();
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * @comment :
	 */
	public void debug(String message) {
		if (logLevel == 5) {
			String logDir = Config.getInstance().getString("log.dir");

			try {
				FileOutputStream file = new FileOutputStream(logDir + File.separator + "debug_" + DateUtil.getCurrentDateInfo("1") + ".log", true);
				PrintWriter writer = new PrintWriter(new OutputStreamWriter(file, "UTF-8"));
				Exception e = new Exception();
				StackTraceElement element = e.getStackTrace()[2];
				writer.println(DateUtil.getCurrentDateInfo("7") + " (" + element.getClassName().substring(element.getClassName().lastIndexOf(".") + 1) + ") Method : " + element.getMethodName()
						+ ", Line : " + element.getLineNumber());
				writer.println("    " + message);
				writer.println();
				writer.close();
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * @comment :
	 */
	public int getLogLevel() {
		return logLevel;
	}

	/**
	 * @comment :
	 */
	public static void setInstance(LogWriter instance) {
		LogWriter.instance = instance;
	}

	/**
	 * @comment :
	 */
	public void setLogLevel(int logLevel) {
		this.logLevel = logLevel;
	}

	/**
	 * @comment :
	 */
	private char getLogLevelChar(int logLevel) {
		switch (logLevel) {
		case DEBUG_LOG:
			return DEBUG_LOG_LABEL;
		case INFO_LOG:
			return INFO_LOG_LABEL;
		case ERROR_LOG:
			return ERROR_LOG_LABEL;
		case WARNING_LOG:
			return WARNING_LOG_LABEL;
		default:
			return DEBUG_LOG_LABEL;
		}
	}
}